.equ  DecompressFileSizeMax             , 32*1024
.equ  KernelFileSizeMax                 ,0x400000
.equ  DecompressFilePhysicalAddress     ,0x100000
.equ  KernelELFPhysicalAddress          ,DecompressFilePhysicalAddress+DecompressFileSizeMax
.equ  KernelDistractBuffer              ,0x600000
.equ  KernelActualDestination           ,0x200000
.equ  ELFBufferActualOffset             ,KernelDistractBuffer-KernelActualDestination
.equ  ELF_e_ident_Offset                       ,0    #16
.equ  ELF_e_type_Offset                        ,16   #2
.equ  ELF_e_machine_Offset                     ,18   #2
.equ  ELF_e_entry_Offset                       ,24   #4
.equ  ELF_e_phoff_Offset                       ,28   #4
.equ  ELF_e_ehsize_Offset                      ,40   #2
.equ  ELF_e_phentsize_Offset                   ,42   #2
.equ  ELF_e_phnum_Offset                       ,44   #2
.equ   PH_p_type_Offset                        ,0    #4
.equ   PH_p_offset_Offset                      ,4    #4 
.equ   PH_p_vaddr_Offset                       ,8    #4
.equ   PH_p_filesz_Offset                      ,16   #4
.equ   PH_p_memsz_Offset                       ,20   #4
.equ  ELF_Magic                                ,0x464C457F   #FLE
.equ  PT_LOAD                                  ,1
.equ  KernelParametersCountContainer   ,  0x5000
.equ  KernelParametersNextContainer    ,  0x5004
.equ  KernelParametersSize             ,  32
.equ  KernelParametersLabelStartEndVA  ,  3
.code32
.global  extract_start
.section .text
extract_start:
   jmp   LABEL_START
   MinVirtualAddress:     .int  0
   MaxVirtualAddress:     .int  0
LABEL_START:
   movl  $KernelELFPhysicalAddress , %eax
   movl  (%eax),%ebx
   cmpl  $ELF_Magic,%ebx
   jne   LABEL_ELFMAGICWRONG
   movl  ELF_e_entry_Offset(%eax),%ebx
   movl  %ebx,MinVirtualAddress
   movw  ELF_e_type_Offset(%eax),%bx
   cmpw  $2,%bx
   jne   LABEL_ELFTYPEWRONG
   movl  ELF_e_phoff_Offset(%eax),%ebx
   addl  %eax,%ebx
   movw  ELF_e_phnum_Offset(%eax),%cx
LABEL_GOONDISTRACT:
   cmpw  $0,%cx
   je    LABEL_ELFDISTRACTOVER
   subw  $1,%cx
   movl  PH_p_type_Offset(%ebx),%edx
   cmpl  $PT_LOAD,%edx   
   jne   LABEL_NEXTPROGRAMHEADER
   movl  PH_p_offset_Offset(%ebx),%edx
   addl  %eax,%edx
   movl  %edx,%esi
   movl  PH_p_vaddr_Offset(%ebx),%edi

   addl  PH_p_memsz_Offset(%ebx),%edi
   subl  $1,%edi
   cmp   %edi ,MaxVirtualAddress
   ja    LABEL_NOCHANGE
   movl  %edi ,MaxVirtualAddress
LABEL_NOCHANGE:
   addl  $1,%edi
   subl  PH_p_memsz_Offset(%ebx),%edi
   

   addl  $ELFBufferActualOffset,%edi
   movl  PH_p_filesz_Offset(%ebx),%edx
   pushl %edx
   pushl %esi
   pushl %edi
   call  MemoryCopy
   addl  $12,%esp
LABEL_NEXTPROGRAMHEADER:
   addl  42(%eax),%ebx
   jmp   LABEL_GOONDISTRACT
LABEL_ELFDISTRACTOVER:
   
   movl  $KernelParametersCountContainer,%eax
   incl  (%eax)
   movl  $KernelParametersNextContainer,%eax
   movl  (%eax),%ebx
   addl  $KernelParametersSize,(%eax)
   movl  $KernelParametersLabelStartEndVA,(%ebx)
   movl  MinVirtualAddress,%eax
   movl  %eax,4(%ebx)
   movl  MaxVirtualAddress,%eax
   subl  MinVirtualAddress,%eax
   addl  $1,%eax
   movl  %eax,8(%ebx)

   movl  $KernelFileSizeMax,%ecx
   movl  $KernelActualDestination,%edi
   movl  $KernelDistractBuffer,%esi
   rep   movsb
   ljmpl $8,$KernelActualDestination
LABEL_ELFMAGICWRONG:
LABEL_ELFTYPEWRONG:
   jmp .
   
MemoryCopy:
   pushl  %ebp
   movl   %esp,%ebp
   pushl  %ecx
   pushl  %edi
   pushl  %esi
   movl   8(%ebp),%edi
   movl   12(%ebp),%esi
   movl   16(%ebp),%ecx
   rep    movsb
   popl   %esi
   popl   %edi
   popl   %ecx
   popl   %ebp
   ret
